import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_common_util/net/base_response.dart';
import 'package:flutter_common_util/net/handle_exception.dart';
import 'package:flutter_common_util/net/request_method.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';
import 'dart:convert';

typedef SuccessCallBack = Function(BaseResponse);
typedef FailCallBack = Function(int code, String msg);
typedef FromJsonCallBack = Function(dynamic json);

class DioManager {
  static final DioManager instance = DioManager._internal();

  factory DioManager() => instance;

  static late Dio _dio;

  DioManager._internal() {
    _dio = Dio();
  }
  //启动时候调用
  initDio(
    String baseUrl, {
    List<Interceptor>? interceptors, //拦截器
    Transformer? transformer, //转换器
    int connectTimeout = 5000,
    int receiveTimeout = 3000,
  }) {
    _dio.options.baseUrl = baseUrl;
    _dio.options.connectTimeout = connectTimeout;
    _dio.options.receiveTimeout = receiveTimeout;
    if (interceptors != null && interceptors.isNotEmpty) {
      _dio.interceptors.addAll(interceptors);
    }
    if (transformer != null) {
      _dio.transformer = transformer;
    }
    //添加请求、响应拦截器
    // dio.interceptors.add(DioInterceptors());
    //添加日志打印
    if (!kReleaseMode) {
      //debug
      _dio.interceptors.add(PrettyDioLogger(
        //添加日志格式化工具类
        requestHeader: true,
        requestBody: true,
        responseBody: true,
        responseHeader: true,
        compact: false,
        maxWidth: 1024,
        logPrint: (object) => print(object),
      ));
    }
  }

  //切换环境（由开发环境切换到正式环境）
  void changeEnv(String baseUrl) {
    _dio.options.baseUrl = baseUrl;
  }

  ///发送请求
  Future<BaseResponse<T>> request<T>(
    String path, {
    FromJsonCallBack? fromJson,
    SuccessCallBack? successCallback,
    FailCallBack? errorCallback,
    RequestMethod method = RequestMethod.get,
    dynamic data, //表单提交
    Map<String, dynamic>? params, //查询参数
    String? baseUrl, //不同服务器
    CancelToken? cancelToken, //是否能取消请求
    ProgressCallback? onSendProgress, //监听发送请求的进度
    ProgressCallback? onReceiveProgress, //监听接受的进度
  }) async {
    const methodValues = {
      RequestMethod.get: 'GET',
      RequestMethod.post: 'POST',
      RequestMethod.put: 'PUT',
      RequestMethod.delete: 'DELETE',
      RequestMethod.patch: 'PATCH',
      RequestMethod.head: 'HEAD',
    };
    _dio.options.method = methodValues[method]!;
    //构建url,如果 path中以http 或 https开头 则url不做处理,（还要对比源做比较）
    if (!(path.indexOf('http://') == 0 || path.indexOf('https://') == 0)) {
      //判断是否设置了全局的baseUrl
      if (_dio.options.baseUrl.isEmpty) {
        //如果不为空则不需要处理
        //没设置则判断请求是否带上了
        if (baseUrl == null || baseUrl.isEmpty) {
          throw 'please initDio first';
        } else {
          path = baseUrl + path; //还存在问题
          // print("请求路由->$path");
        }
      }
    }
    try {
      Response response = await _dio.request(path,
          data: data,
          queryParameters: params,
          cancelToken: cancelToken,
          onSendProgress: onSendProgress,
          onReceiveProgress: onReceiveProgress);
      // print(response.data.toString());

      if (response.statusCode == 200) {
        //网路层
        //判断返回时json还是String
        Map<String, dynamic> map;
        //ResponseType(json 格式、stream 流、plain utf8字符串、bytys,List<int>数据流)
        //常见的方式有 json 和 plain,(后面俩种再完善)
        if (response.requestOptions.responseType == ResponseType.json) {
          //返回json
          map = response.data;
        } else {
          // map = convert.jsonDecode(response.data); //json 字符串
          map = json.decode(response.data);
        }
        // Map<String, dynamic> dataMap = json.decode(json.encode(response.data));
        BaseResponse<T> respose;
        if (fromJson == null) {
          respose = BaseResponse.fromJson(map);
        } else {
          respose = BaseResponse<T>.fromJson(map,
              fromJsonT: (json) => fromJson(json));
        }
        //自定义状态值(也可以是其他标志)
        if (respose.status == 200) {
          //还有其他值比如token失效
          if (successCallback != null) {
            successCallback(respose);
          } else {
            return respose;
          }
        } else {
          //参数错误等等（状态码和后台协商）
          //token失效（刷新token或重新登录）
          if (errorCallback != null) {
            errorCallback(respose.status ?? 0, respose.msg ?? "数据错误");
          } else {
            return respose;
          }
        }
      } //除了200其他都视为异常
      // } else {
      //   if (errorCallback != null) {
      //     errorCallback(respose);
      //   } else {
      //     // return <String, dynamic>{};
      //     respose = BaseRespose(
      //         status: response.statusCode, msg: response.statusMessage);
      //     return respose;
      //   }
      // }
    } on DioError catch (e) {
      // print('请求异常：${e.toString()}');
      final NetError error = DioHandleException.handleException(e);
      if (errorCallback != null) {
        errorCallback(error.code, error.msg);
      } else {
        BaseResponse<T> respose =
            BaseResponse(status: error.code, msg: error.msg);
        return respose;
      }
      rethrow;
    }
    return BaseResponse();
    // return <String, dynamic>{};
  }
}
